package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSONObject;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.threadlocal.CommonOperateLogHolder;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.AbstractEntityEventHandler;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.ProcessCompletedPostProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.ThirdPlatformCallbackResolver;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.HttpUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.common.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.common.api.delegate.event.FlowableEventType;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * Handler - 流程实例完成后通知第三方平台
 *
 * @author lilh
 * @date 2019-02-20 22:56
 */
@Component
public class CallbackThirdPlatformAfterProcessInstanceCompletedHandler extends AbstractEntityEventHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ThirdPlatformCallbackResolver urlResolver;

    @Lazy
    @Autowired(required = false)
    private List<ProcessCompletedPostProcessor> processCompletedPostProcessors = new ArrayList<>();

    @Override
    public FlowableEventType getEventType() {
        return FlowableEngineEventType.PROCESS_COMPLETED;
    }

    @Override
    protected void doHandle(FlowableEntityEventImpl event) {
        sendProcessCompletedEventToClient(event);
        executePostProcessor(event);
    }

    private void executePostProcessor(FlowableEntityEventImpl event) {
        ExecutionEntity executionEntity = (ExecutionEntity) event.getEntity();
        for (ProcessCompletedPostProcessor processor : processCompletedPostProcessors) {
            try {
                processor.process(executionEntity);
            } catch (Exception e) {
                logger.warn(ExceptionUtil.stacktraceToOneLineString(e));
            }
        }
    }

    private void sendProcessCompletedEventToClient(FlowableEntityEventImpl event) {
        String url = urlResolver.resolveCallbackUrlByProcessInstanceId(event.getProcessInstanceId());
        if (StringUtils.isEmpty(url)) {
            logger.info("没有配置url，不用处理");
            return;
        }
        ProcessCompleteNotifyMsg msg = new ProcessCompleteNotifyMsg();
        msg.setProcessInstanceId(event.getProcessInstanceId());
        CommonOperateLogHolder.setProcessInstanceCompletedFlag(true);
        logger.info("回调流程完成请求数据为：{}", JSONObject.toJSONString(msg));
        String result = HttpUtils.sendHttpPost(url, JSONObject.toJSONString(msg));
        logger.info("回调流程完成返回结果: {}", result);
    }

    static class ProcessCompleteNotifyMsg {

        private String commandCode = "reportProcessState";

        private String processInstanceId;

        private String processInstanceState = "2";

        private String serial = "1";

        public String getCommandCode() {
            return commandCode;
        }

        public void setCommandCode(String commandCode) {
            this.commandCode = commandCode;
        }

        public String getProcessInstanceId() {
            return processInstanceId;
        }

        public void setProcessInstanceId(String processInstanceId) {
            this.processInstanceId = processInstanceId;
        }

        public String getProcessInstanceState() {
            return processInstanceState;
        }

        public void setProcessInstanceState(String processInstanceState) {
            this.processInstanceState = processInstanceState;
        }

        public String getSerial() {
            return serial;
        }

        public void setSerial(String serial) {
            this.serial = serial;
        }
    }
}
